package com.yue.net;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * Created by qiuyang on 11/04/2017.
 */
public class Ping {

    public static void main(String[] args) throws Exception {
        String ip = "220.189.213.134";
//        String ip = "10.0.23.9";
//        String ip = "ipalmap.com";
        String localIP = "10.0.11.66";
//        isAddressAvailable(ip);

//        printReachableIP(InetAddress.getByName(ip), 6060);

        isReachable(InetAddress.getLocalHost(), InetAddress.getByName(ip), 6060, 5000);
//        isReachable(InetAddress.getByName(localIP), InetAddress.getByName(ip), 8081, 5000);
    }

    public static void isAddressAvailable(String ip) {
        try {
            InetAddress inetAddress = InetAddress.getByName(ip);
            if (inetAddress instanceof Inet4Address) {
                System.out.println(ip + " is ipv4 address");
            } else if (inetAddress instanceof Inet6Address) {
                System.out.println(ip + " is ipv6 address");
            } else {
                System.out.println(ip + " is unrecongized");
            }

            if (inetAddress.isReachable(5000)) {
                System.out.println("Success - ping " + ip + " with no interface specified");
            } else {
                System.out.println("Failure - ping " + ip + " with no interface specified");
            }

            System.out.println("\n----------Try different intefaces ---------------\n");

            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                System.out.println("Checking interface, DisplayName : " + networkInterface.getDisplayName() + ", Name : " + networkInterface.getDisplayName());
                if (inetAddress.isReachable(networkInterface, 0, 5000)) {
                    System.out.println("Success - ping " + ip);
                } else {
                    System.out.println("Failure - ping " + ip);
                }

                Enumeration<InetAddress> ips = networkInterface.getInetAddresses();
                while (ips.hasMoreElements()) {
                    System.out.println("IP : " + ips.nextElement().getHostAddress());
                }

                System.out.println("-----");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void printReachableIP(InetAddress remoteAddr, int port) {
        String retIP = null;
        Enumeration<NetworkInterface> netInterfaces;
        try {
            netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                Enumeration<InetAddress> localAddrs = ni.getInetAddresses();
                while (localAddrs.hasMoreElements()) {
                    InetAddress localAddr = localAddrs.nextElement();
                    if (isReachable(localAddr, remoteAddr, port, 5000)) {
                        retIP = localAddr.getHostAddress();
                        break;
                    }
                }
            }
        } catch (SocketException e) {
            System.out.println("Error occurred while listing all the local network addresses.");
        }
        if (retIP == null) {
            System.out.println(" NULL reachable local IP is found !");
        } else {
            System.out.println(" Reachable local IP is found, it is " + retIP);
        }
    }

    public static boolean isReachable(InetAddress localInetAddr, InetAddress remoteInetAddr, int port, int timeout) {
        boolean isReachable = false;
        Socket socket = null;
        try {
            socket = new Socket(); // 端口号设置为 0 表示在本地挑选一个可用端口进行连接
            SocketAddress localSocketAddr = new InetSocketAddress(localInetAddr, 0);
            socket.bind(localSocketAddr);
            InetSocketAddress endpointSocketAddr = new InetSocketAddress(remoteInetAddr, port);
            socket.connect(endpointSocketAddr, timeout);
            System.out.println("SUCCESS - connection established !Local:" + localInetAddr.getHostAddress()
                    + " remote: " + remoteInetAddr.getHostAddress() + " port " + port);
            isReachable = true;
        } catch (IOException e) {
            System.out.println("FAILRE - Can not connect! Local: " + localInetAddr.getHostAddress()
                    + " remote: " + remoteInetAddr.getHostAddress() + " port " + port);
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    System.out.println("Error occurred while closing socket..");
                }
            }
        }
        return isReachable;
    }

}
